﻿
using Sai.Cecil;
using Sai.Core;
using Sai.Core.Introspection;
using Sai.Core.Rules;

namespace Sai.Test.TestDataBuilders
{
    public class AssemblyDifferenceBuilder
    {
        private string oldCode;
        private string newCode;

        private IAssemblyRule rule;
        private IProductReleaseProject project;
        private IAssemblyIntrospector introspector = new MonoCecilAssemblyIntrospector();

        public static AssemblyDifferenceBuilder Differences ()
        {
            return new AssemblyDifferenceBuilder();
        }

        public AssemblyDifferenceBuilder CodeWas(string oldCode)
        {
            this.oldCode = oldCode;

            return this;
        }

        public AssemblyDifferenceBuilder CodeIsNow(string newCode)
        {
            this.newCode = newCode;

            return this;
        }

        public AssemblyDifferenceBuilder CheckedUsing(IAssemblyRule rule)
        {
            this.rule = rule;

            return this;
        }

        public AssemblyDifferenceBuilder WithProject(IProductReleaseProject project)
        {
            this.project = project;

            return this;
        }

        public AssemblyDifferenceBuilder UsingInspector(IAssemblyIntrospector inspector)
        {
            this.introspector = inspector;

            return this;
        }

        public AssemblyDifference Build()
        {
            using (OnTheFlyAssembly oldAssembly = new OnTheFlyAssembly())
            {
                oldAssembly.Compile(this.oldCode);

                using (OnTheFlyAssembly newAssembly = new OnTheFlyAssembly())
                {
                    newAssembly.Compile(this.newCode);

                    var oldResult = this.introspector.IntrospectAssembly(oldAssembly.ProductAssembly);
                    var newResult = this.introspector.IntrospectAssembly(newAssembly.ProductAssembly);

                    AssemblyDifference diff = new AssemblyDifference();

                    if (this.project == null)
                        this.project = Mock.MinimalProject();

                    rule.Validate(oldResult, newResult, diff);

                    return diff;
                }
            }
        }

    }
}
